package errcode

import (
	"fmt"
	"runtime/debug"
	"strconv"
	"strings"

	"gitee.com/u-language/u-language/ucom/internal/utils"
)

// 代码错误提示
type Msg interface {
	//返回提示信息
	Msg() string
}

var _ Msg = MsgAssignTypeIsNotEqual{}
var _ Msg = MsgOpexprTypeIsNotEqual{}
var _ Msg = MsgUnknownSymbol{}
var _ Msg = MsgSymbol{}
var _ Msg = MsgBracesNoEqual{}
var _ Msg = MsgSymbolRepeat{}
var _ Msg = MsgCallTypeIsNotEqual{}
var _ Msg = MsgReturnTypeIsNotEqual{}
var _ Msg = MsgLabelNoExist{}
var _ Msg = MsgAssignToConst{}
var _ Msg = MsgNumberOfParameNoMatch{}
var _ Msg = MsgSelectorLNoSelectorR{}
var _ Msg = MsgDiffFileHavaDiffPackageDecl{}
var _ Msg = MsgRecursiveTypeErr{}
var _ Msg = MsgPackageNameNoEqualDirName{}
var _ Msg = MsgBracketsNoEqual{}
var _ Msg = MsgUnexpected{}

var (
	dest                   string = "目的操作数的类型："
	src                    string = "源操作数的类型："
	src1                   string = "左边的类型："
	src2                   string = "右边的类型："
	oTINEM                 string = "运算表达式类型不相等"
	symbol_name                   = "符号名="
	leftBraceNum           string = "左大括号数量："
	rightBraceNum          string = "右大括号数量："
	tnossb                 string = "分号数量应该是：2" //The number of semicolons should be
	asq                           = "实际的分号数量："  //Actual semicolon quantity
	parame                        = "参数声明的类型"
	passParame                    = "被传递的参数的类型" //Passed parameters
	ntp                           = "第%d个参数 "   //n th parameter
	ret_rt                        = "返回的类型="
	ret_dt                        = "声明的类型="
	label_Noexist                 = "不存在的标签="
	assignToConst                 = "为常量 %s 赋值"
	num_of_parame_no_match        = "%s 声明的参数数量=%d 传递的参数数量=%d" //NumberOfParameNoMatch
	left                          = "左值="
	right                         = "右值="
	dfhdpd                        = "包声明有 %s %s"
	sactne                        = "switch类型=%s case类型=%s"
	Aoldad                        = "出现在%s的第%d行 和 %s的第%d行" //Appears on line% d of% s and line% d of% s
	depend_on                     = "依赖于"
	packagenandDir                = "包名=%s 目录名=%s"
	leftBracketNum         string = "左中括号数量："
	rightBracketNum        string = "右中括号数量："
	unexpected                    = "意外的：%s"
	expectedAndFound              = "需要 %s , 找到 %s"
	unexpected2                   = "意外的：%s 意外的：%s"
)

// MsgAssignTypeIsNotEqual 表示一个赋值类型不相等错误
type MsgAssignTypeIsNotEqual struct {
	//目的操作数的类型
	DestType string
	//源操作数的类型
	SrcType string
	stack   []byte
}

// 创建MsgAssignTypeIsNotEqual
func NewMsgAssignTypeIsNotEqual(DestType string, SrcType string) MsgAssignTypeIsNotEqual {
	ret := MsgAssignTypeIsNotEqual{DestType: remove_package_name(DestType), SrcType: remove_package_name(SrcType)}
	if Debug {
		ret.stack = debug.Stack()
	}
	return ret
}

// Msg 返回提示信息
func (msg MsgAssignTypeIsNotEqual) Msg() string {
	var buf strings.Builder
	buf.Grow(80)
	buf.WriteString("\n")
	buf.WriteString(dest)
	buf.WriteString(msg.DestType)
	buf.WriteString("\n")
	buf.WriteString(src)
	buf.WriteString(msg.SrcType)
	buf.WriteString("\n")
	if msg.stack != nil {
		buf.Write(msg.stack)
	}
	return buf.String()
}

func (msg MsgAssignTypeIsNotEqual) Is(b Msg) bool {
	if bm, ok := b.(MsgAssignTypeIsNotEqual); ok {
		return bm.DestType == msg.DestType && bm.SrcType == msg.SrcType
	}
	return false
}

// MsgOpexprTypeIsNotEqual 表示一个运算表达式类型不相等错误
type MsgOpexprTypeIsNotEqual struct {
	//应该的类型
	src1Type string
	//现实的类型
	src2Type string
}

// 创建MsgOpexprTypeIsNotEqual
func NewMsgOpexprTypeIsNotEqual(src1Type string, src2Type string) MsgOpexprTypeIsNotEqual {
	return MsgOpexprTypeIsNotEqual{src1Type: remove_package_name(src1Type), src2Type: remove_package_name(src2Type)}
}

// Msg 返回提示信息
func (msg MsgOpexprTypeIsNotEqual) Msg() string {
	var buf strings.Builder
	buf.Grow(70)
	buf.WriteString(oTINEM)
	buf.WriteString("\n")
	buf.WriteString(src1)
	buf.WriteString(msg.src1Type)
	buf.WriteString("\n")
	buf.WriteString(src2)
	buf.WriteString(msg.src2Type)
	buf.WriteString("\n")
	return buf.String()
}

// MsgUnknownSymbol 表示一个未知的符号错误
type MsgUnknownSymbol struct {
	//未知的符号名
	Name  string
	stack []byte
}

// 创建MsgUnknownSymbol
func NewMsgUnknownSymbol(Name string) MsgUnknownSymbol {
	msg := MsgUnknownSymbol{Name: remove_package_name(Name)}
	if Debug {
		msg.stack = debug.Stack()
	}
	return msg
}

// Msg 返回提示信息
func (msg MsgUnknownSymbol) Msg() string {
	var buf strings.Builder
	buf.Grow(35)
	buf.WriteString("=")
	buf.WriteString(msg.Name)
	buf.WriteString("\n")
	if Debug {
		buf.Write(msg.stack)
	}
	return buf.String()
}

func (msg MsgUnknownSymbol) Is(eq Msg) bool {
	if v, ok := eq.(MsgUnknownSymbol); ok {
		return v.Name == msg.Name
	}
	return false
}

// MsgSymbol 表示一个报错信息中的符号名
type MsgSymbol struct {
	//变量名
	Name string
}

// 创建MsgSymbol
func NewMsgSymbol(Name string) MsgSymbol {
	return MsgSymbol{Name: remove_package_name(Name)}
}

// Msg 返回提示信息
func (msg MsgSymbol) Msg() string {
	var buf strings.Builder
	buf.Grow(35)
	buf.WriteString(symbol_name)
	buf.WriteString(msg.Name)
	return buf.String()
}

// MsgBracesNoEqual 表示左大括号和右大括号数量不匹配
type MsgBracesNoEqual struct {
	Left  int
	Right int
}

func NewMsgBracesNoEqual(Left int, Right int) MsgBracesNoEqual {
	return MsgBracesNoEqual{Left: Left, Right: Right}
}

// Msg 返回提示信息
func (msg MsgBracesNoEqual) Msg() string {
	var buf strings.Builder
	buf.Grow(40)
	buf.WriteString(leftBraceNum)
	buf.WriteString(strconv.Itoa(msg.Left))
	buf.WriteString(" ")
	buf.WriteString(rightBraceNum)
	buf.WriteString(strconv.Itoa(msg.Right))
	buf.WriteString("\n")
	return buf.String()
}

// MsgNumberOfSemicolons 表示分号数量错误，目前用于for语句
type MsgNumberOfSemicolons struct {
	Num int
}

func NewMsgNumberOfSemicolons(Num int) MsgNumberOfSemicolons {
	return MsgNumberOfSemicolons{Num: Num}
}

// Msg 返回提示信息
func (msg MsgNumberOfSemicolons) Msg() string {
	var buf strings.Builder
	buf.Grow(40)
	buf.WriteString(tnossb)
	buf.WriteString(" ")
	buf.WriteString(asq)
	buf.WriteString(strconv.Itoa(msg.Num))
	buf.WriteString("\n")
	return buf.String()
}

// MsgSymbolRepeat 表示一个重复的符号名
type MsgSymbolRepeat struct {
	//未知的符号名
	Name                 string
	FileName1, FileName2 string
	LineNum1, LineNum2   int
}

// 创建MsgSymbolRepeat
func NewMsgSymbolRepeat(Name string, FileName1, FileName2 string, LineNum1, LineNum2 int) MsgSymbolRepeat {
	return MsgSymbolRepeat{Name: remove_package_name(Name), FileName1: FileName1, FileName2: FileName2, LineNum1: LineNum1, LineNum2: LineNum2}
}

// Msg 返回提示信息
func (msg MsgSymbolRepeat) Msg() string {
	var buf strings.Builder
	buf.Grow(35)
	buf.WriteString("=")
	buf.WriteString(msg.Name)
	buf.WriteString(fmt.Sprintf(Aoldad, msg.FileName1, msg.LineNum1, msg.FileName2, msg.LineNum2))
	buf.WriteString("\n")
	return buf.String()
}

// MsgCallTypeIsNotEqual 表示一个函数调用类型不相等错误
type MsgCallTypeIsNotEqual struct {
	//参数的类型
	src1Type string
	//被传递的类型
	src2Type string
	//第几个参数
	num int
}

// 创建MsgCallTypeIsNotEqual
func NewMsgCallTypeIsNotEqual(ParameType string, src2Type string, num int) MsgCallTypeIsNotEqual {
	return MsgCallTypeIsNotEqual{src1Type: remove_package_name(ParameType), src2Type: remove_package_name(src2Type), num: num}
}

// Msg 返回提示信息
func (msg MsgCallTypeIsNotEqual) Msg() string {
	var buf strings.Builder
	buf.Grow(70)
	buf.WriteString(fmt.Sprintf(ntp, msg.num))
	buf.WriteString(parame)
	buf.WriteString(msg.src1Type)
	buf.WriteString(" ")
	buf.WriteString(passParame)
	buf.WriteString(msg.src2Type)
	buf.WriteString("\n")
	return buf.String()
}

// MsgreturnTypeIsNotEqual 表示一个返回语句类型不相等错误
type MsgReturnTypeIsNotEqual struct {
	//声明的类型
	DeclType string
	//返回的类型
	RetType string
}

// 创建MsgReturnTypeIsNotEqual
func NewMsgReturnTypeIsNotEqual(DeclType string, RetType string) MsgReturnTypeIsNotEqual {
	return MsgReturnTypeIsNotEqual{DeclType: remove_package_name(DeclType), RetType: remove_package_name(RetType)}
}

// Msg 返回提示信息
func (msg MsgReturnTypeIsNotEqual) Msg() string {
	var buf strings.Builder
	buf.Grow(70)
	buf.WriteString(ret_dt)
	buf.WriteString(msg.DeclType)
	buf.WriteString(" ")
	buf.WriteString(ret_rt)
	buf.WriteString(msg.RetType)
	buf.WriteString("\n")
	return buf.String()
}

// MsgLabelNoExist 表示一个不存在的标签错误
// 缩写：Label that does not exist 缩写成 LabelNoExist
type MsgLabelNoExist struct {
	//不存在的标签名
	Label string
}

// 创建MsgLabelNoExist
func NewMsgLabelNoExist(Label string) MsgLabelNoExist {
	return MsgLabelNoExist{Label: Label}
}

// Msg 返回提示信息
func (msg MsgLabelNoExist) Msg() string {
	var buf strings.Builder
	buf.Grow(70)
	buf.WriteString(label_Noexist)
	buf.WriteString(msg.Label)
	buf.WriteString("\n")
	return buf.String()
}

// 缩写： Assign values to constants 缩写成 AssignToConst
// MsgAssignToConst 表示一个对常量赋值错误
type MsgAssignToConst struct {
	Name string
}

// 创建MsgAssignToConst
func NewMsgAssignToConst(name string) MsgAssignToConst {
	return MsgAssignToConst{Name: remove_package_name(name)}
}

// Msg 返回提示信息
func (msg MsgAssignToConst) Msg() string {
	return fmt.Sprintf(assignToConst, msg.Name)
}

// 缩写：Number of parameters does not match 缩写成 NumberOfParameNoMatch
// MsgNumberOfParameNoMatch 表示一个参数数量不匹配错误
type MsgNumberOfParameNoMatch struct {
	FuncName string
	//调用（实际传递的参数）数量
	CallerNum int
	//被调者（函数声明的参数）数量
	CalleeNum int
}

// 创建MsgNumberOfParameNoMatch
func NewMsgNumberOfParameNoMatch(CallerNum int, CalleeNum int, FuncName string) MsgNumberOfParameNoMatch {
	return MsgNumberOfParameNoMatch{CallerNum: CallerNum, CalleeNum: CalleeNum, FuncName: FuncName}
}

// Msg 返回提示信息
func (msg MsgNumberOfParameNoMatch) Msg() string {
	return fmt.Sprintf(num_of_parame_no_match, msg.FuncName, msg.CalleeNum, msg.CallerNum)
}

// 缩写： The selector left value does not have a selector right value 缩写成SelectorLNoSelectorR
// MsgSelectorLNoSelectorR 代表一个选择器左值没有选择器右值的错误
type MsgSelectorLNoSelectorR struct {
	LeftValue  string
	RightValue string
	stack      []byte
}

func NewMsgSelectorLNoSelectorR(LeftValue string, RightValue string) MsgSelectorLNoSelectorR {
	ret := MsgSelectorLNoSelectorR{LeftValue: remove_package_name(LeftValue), RightValue: remove_package_name(RightValue)}
	if Debug {
		ret.stack = debug.Stack()
	}
	return ret
}

// Msg 返回提示信息
func (msg MsgSelectorLNoSelectorR) Msg() string {
	s := fmt.Sprintf("%s %s \t %s %s", left, msg.LeftValue, right, msg.RightValue)
	if Debug {
		return s + string(msg.stack)
	}
	return s
}

func (msg MsgSelectorLNoSelectorR) Is(eq Msg) bool {
	if eqm, ok := eq.(MsgSelectorLNoSelectorR); ok {
		return msg.LeftValue == eqm.LeftValue && msg.RightValue == eqm.RightValue
	}
	return false
}

// remove_package_name 返回去除包名的字符串
func remove_package_name(s string) string {
	_, s = utils.Split_package_name(s)
	return s
}

// 缩写：Different file declarations have different package declarations 缩写成 DiffFileHavaDiffPackageDecl
// MsgDiffFileHavaDiffPackageDecl 表示一个不同文件声明的包声明不同附加错误
type MsgDiffFileHavaDiffPackageDecl struct {
	Decl1, Decl2 string
}

// 创建MsgDiffFileHavaDiffPackageDecl
func NewMsgDiffFileHavaDiffPackageDecl(Decl1, Decl2 string) MsgDiffFileHavaDiffPackageDecl {
	return MsgDiffFileHavaDiffPackageDecl{Decl1: Decl1, Decl2: Decl2}
}

// Msg 返回提示信息
func (msg MsgDiffFileHavaDiffPackageDecl) Msg() string {
	return fmt.Sprintf(dfhdpd, msg.Decl1, msg.Decl2)
}

// 缩写：Switch and case types are not equal 缩写成 SwitchAndCaseTypNoEqual
// MsgSwitchAndCaseTypNoEqual 表示一个switch和case类型不相等
type MsgSwitchAndCaseTypNoEqual struct {
	SwitchTyp, CaseTyp string
}

// 创建MsgSwitchAndCaseTypNoEqual
func NewMsgSwitchAndCaseTypNoEqual(SwitchTyp, CaseTyp string) MsgSwitchAndCaseTypNoEqual {
	return MsgSwitchAndCaseTypNoEqual{SwitchTyp: SwitchTyp, CaseTyp: CaseTyp}
}

// Msg 返回提示信息
func (msg MsgSwitchAndCaseTypNoEqual) Msg() string {
	return fmt.Sprintf(sactne, msg.SwitchTyp, msg.CaseTyp)
}

// MsgRecursiveTypeErr 表示一个递归类型附加错误
type MsgRecursiveTypeErr struct {
	Dep []string
}

// 创建MsgRecursiveTypeErr
func NewMsgRecursiveTypeErr(finaldep string) MsgRecursiveTypeErr {
	return MsgRecursiveTypeErr{Dep: []string{"", finaldep}}
}

// Msg 返回提示信息
func (msg MsgRecursiveTypeErr) Msg() string {
	var buf strings.Builder
	for _, v := range msg.Dep[:len(msg.Dep)-1] {
		buf.WriteString(v)
		buf.WriteString(depend_on)
		buf.WriteString("\n")
	}
	buf.WriteString(msg.Dep[len(msg.Dep)-1])
	return buf.String()
}

// MsgPackageNameNoEqualDirName 表示一个包名不等于目录名附加错误
type MsgPackageNameNoEqualDirName struct {
	PackageName string
	DirName     string
}

// 创建 MsgPackageNameNoEqualDirName
func NewMsgPackageNameNoEqualDirName(PackageName string, DirName string) MsgPackageNameNoEqualDirName {
	return MsgPackageNameNoEqualDirName{PackageName: PackageName, DirName: DirName}
}

// Msg 返回提示信息
func (msg MsgPackageNameNoEqualDirName) Msg() string {
	return fmt.Sprintf(packagenandDir, msg.PackageName, msg.DirName)
}

// MsgBracketsNoEqual 表示左中括号和右中括号数量不匹配
type MsgBracketsNoEqual struct {
	Left  int
	Right int
}

func NewMsgBracketsNoEqual(Left int, Right int) MsgBracketsNoEqual {
	return MsgBracketsNoEqual{Left: Left, Right: Right}
}

// Msg 返回提示信息
func (msg MsgBracketsNoEqual) Msg() string {
	var buf strings.Builder
	buf.Grow(60)
	buf.WriteString(leftBracketNum)
	buf.WriteString(strconv.Itoa(msg.Left))
	buf.WriteString(" ")
	buf.WriteString(rightBracketNum)
	buf.WriteString(strconv.Itoa(msg.Right))
	buf.WriteString("\n")
	return buf.String()
}

// MsgUnexpected 表示一个意外的字符串
type MsgUnexpected struct {
	Str string
}

func NewMsgUnexpected(str string) MsgUnexpected {
	return MsgUnexpected{Str: str}
}

// Msg 返回提示信息
func (msg MsgUnexpected) Msg() string {
	return fmt.Sprintf(unexpected, msg.Str)
}

// MsgExpectedAndFound 表示一个 需要 x 找到 y 的错误
type MsgExpectedAndFound struct {
	Expected, Found string
}

func NewMsgExpectedAndFound(Expected, Found string) MsgExpectedAndFound {
	return MsgExpectedAndFound{Expected: Expected, Found: Found}
}

// Msg 返回提示信息
func (msg MsgExpectedAndFound) Msg() string {
	return fmt.Sprintf(expectedAndFound, msg.Expected, msg.Found)
}

// MsgUnexpected2 表示一个意外的两个字符串
type MsgUnexpected2 struct {
	Str1 string
	Str2 string
}

func NewMsgUnexpected2(str1, str2 string) MsgUnexpected2 {
	return MsgUnexpected2{Str1: str1, Str2: str2}
}

// Msg 返回提示信息
func (msg MsgUnexpected2) Msg() string {
	return fmt.Sprintf(unexpected2, msg.Str1, msg.Str2)
}
